#include "GameWindow.h"
#include <QPainter>
#include <QRandomGenerator>

GameWindow::GameWindow(QWidget *parent)
    : QMainWindow(parent),
    elapsedTime(0.0f),
    obstacleCount(5),
    horiObstacleCount(0),
    horiSpeed(1.0f),
    score(0),
    rewardBlockCount(0),
    timeCount(0),
    rewardBlock(1120, 800),
    spacebarPressed(false),
    isPause(0) {
    library.load(":/Library.jpg");
    setFixedSize(1120, 800);
    player = new Player(1120, 3);
    ground = new Ground(1120, 800);
    timer = new QTimer(this);

    connect(timer, &QTimer::timeout, this, &GameWindow::updateGame);
    timer->start(pertime);

    scoreTimer = new QTimer(this);
    connect(scoreTimer, &QTimer::timeout, this, &GameWindow::updateScore);
    scoreTimer->start(1000);

    spacebarTimer = new QTimer(this);
    connect(spacebarTimer, &QTimer::timeout, this, &GameWindow::checkSpacebarLongPress);

    for (int i = 0; i < obstacleCount; ++i) {
        obstacles.append(new Obstacle(this, QRandomGenerator::global()->bounded(1000),
                                      -1000 - i * 200, QRandomGenerator::global()->bounded(2)));
    }
}

GameWindow::~GameWindow() {
    delete player;
    delete ground;
    qDeleteAll(obstacles);
    qDeleteAll(horiObstacles);
}

void GameWindow::deleteGame() {
    delete player;
    delete ground;
    qDeleteAll(obstacles);
    qDeleteAll(horiObstacles);
}

void GameWindow::timeForPrepare() {
    timer->stop();
    scoreTimer->stop();
}

void GameWindow::timeForStart() {
    timer->start();
    scoreTimer->start();
}

int GameWindow::getScore() {
    return score;
}

void GameWindow::updateScore() {
    score += 5;
    timeCount++;
    update();
}

void GameWindow::paintEvent(QPaintEvent *event) {
    QPainter painter(this);
    painter.drawImage(0, 0, library.scaled(width(), height()));

    ground->draw(&painter);
    player->draw(&painter);

    for (Obstacle *obs : obstacles) {
        obs->draw(&painter);
    }
    for (HorizontalObstacle *horiObs : horiObstacles) {
        horiObs->draw(&painter);
    }

    rewardBlock.draw(&painter);

    painter.setPen(Qt::white);
    painter.setFont(QFont("Arial", 24));
    painter.drawText(50, 50, QString("分数: %1").arg(score));
    painter.setPen(Qt::white);
    painter.setFont(QFont("Arial", 24));
    painter.drawText(50, 100, QString("生命值: %1").arg(player->getLife()));
    painter.setPen(Qt::white);
    painter.setFont(QFont("Arial", 24));
    painter.drawText(50, 150, QString("魔法书: %1").arg(rewardBlockCount));
    painter.setPen(Qt::white);
    painter.setFont(QFont("Arial", 24));
    painter.drawText(50, 200, QString("能量: %1").arg(player->getEnergy()));
}

void GameWindow::keyPressEvent(QKeyEvent *event) {
    if (event->key() == Qt::Key_Left) {
        player->move(-6.0f);
    } else if (event->key() == Qt::Key_Right) {
        player->move(6.0f);
    } else if (event->key() == Qt::Key_Space) {
        if (!spacebarPressed) {
            spacebarPressed = true;
            spacebarTimer->start(80);
            player->jump();
        }
    } else if (event->key() == Qt::Key_Z) {
        player->scoreSkillAt_Z(GameWindow::score);
    } else if (event->key() == Qt::Key_X) {
        player->scoreSkillAt_X(GameWindow::score, obstacles);
    } else if (event->key() == Qt::Key_Escape && !isPause) {
        timer->stop();
        scoreTimer->stop();
        isPause = 1;
    } else if (event->key() == Qt::Key_Escape && isPause) {
        timer->start();
        scoreTimer->start();
        isPause = 0;
    }
}

void GameWindow::keyReleaseEvent(QKeyEvent *event) {
    if (event->key() == Qt::Key_Space) {
        spacebarPressed = false;
        spacebarTimer->stop();
        player->stopGlide();
    }
}

void GameWindow::checkSpacebarLongPress() {
    if (spacebarPressed) {
        player->startGlide();
    }
}


void GameWindow::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
        int targetX = event->x();
        int targetY = event->y();
        player->shoot(targetX, targetY);
    }
}

void GameWindow::timeGenerate(){
    timeCount++;
}

void GameWindow::updateGame() {
    elapsedTime += (float)pertime / 1000;

    if (elapsedTime >= 3.5f && obstacleCount < 120) {
        obstacles.append(new Obstacle(this, QRandomGenerator::global()->bounded(1200), -30, QRandomGenerator::global()->bounded(2)));
        obstacleCount+=QRandomGenerator::global()->bounded(timeCount/20+1,4*(timeCount/20+1));
        elapsedTime = 0.0f;
    }

    static float horiTimer = 0.0f;
    horiTimer += (float)pertime / 1000;
    if (horiTimer >= 1.2f && horiObstacleCount < timeCount/15*2+2) {
        int y = QRandomGenerator::global()->bounded(400, 700);
        horiSpeed = QRandomGenerator::global()->bounded(2, 7);
        horiObstacles.append(new HorizontalObstacle(y, horiSpeed));
        horiObstacleCount++;
        horiTimer = 0.0f;
    }

    static float rewardTimer = 0.0f;
    rewardTimer += (float)pertime / 1000;
    if (rewardTimer >= 6.0f && !rewardBlock.isActive()) {
        rewardBlock.reset();
        rewardTimer = 0.0f;
    }

    player->update(ground);
    player->updateBullets(obstacles, horiObstacles);

    for (int i = 0; i < obstacles.size(); ++i) {
        obstacles[i]->moveDown();
        if (obstacles[i]->gety() > height()) {
            obstacles[i]->setY(QRandomGenerator::global()->bounded(-80, -10));
            obstacles[i]->setX(QRandomGenerator::global()->bounded(1200));
        }
        if (!player->isInvincible() && player->rect().intersects(obstacles[i]->rect())) {
            player->lifeDown();
            player->activateInvincibility();
        }
    }

    for (int i = 0; i < horiObstacles.size(); ++i) {
        horiObstacles[i]->moveRight();
        if (horiObstacles[i]->rect().x() > 1200) {
            delete horiObstacles[i];
            horiObstacles.removeAt(i--);
            horiObstacleCount--;
        } else if (!player->isInvincible() && player->rect().intersects(horiObstacles[i]->rect())) {
            player->lifeDown();
            player->activateInvincibility();
        }
    }

    if (rewardBlock.checkCollision(player->rectWithRewardBlock())) {
        score += 50;
        rewardBlockCount++;
        player->activateInvincibility();
        player->addGlideEnergy();
        update();
    }

    if (rewardBlockCount >= 24) {
        timer->stop();
        scoreTimer->stop();
        emit gameSuccess();
    }

    if (player->getLife() == 0) {
        timer->stop();
        scoreTimer->stop();
        emit gameFailure();
    }

    update();
}
